<script setup lang="ts">
import { ref } from "vue";

let emit = defineEmits(["onSelected"]);

let fileMap: Record<
  string,
  { url: string; extension: string; file: any; baseUrl: string }
> = {};
let modelFileList = ref<string[]>([]);

function changeUri(item: { uri: string }, baseUrl: string) {
  if (item.uri.startsWith("data:")) {
    return;
  }

  item.uri = fileMap[baseUrl + item.uri].url;
}

function getFileExtension(fileName: string) {
  return fileName.slice(fileName.lastIndexOf(".") + 1);
}

async function getFileList(handle: any, baseUrl: string) {
  for await (const [key, value] of handle.entries()) {
    if (value.kind === "directory") {
      getFileList(value, baseUrl + value.name + "/");
      continue;
    }

    let file = await value.getFile();

    let extension = getFileExtension(key);
    fileMap[baseUrl + key] = {
      url: URL.createObjectURL(file),
      baseUrl,
      extension,
      file,
    };

    if (extension === "gltf" || extension === "glb") {
      modelFileList.value.push(baseUrl + key);
    }
  }
}

async function pickDirectory() {
  // @ts-ignore
  const rootDirHandle = await window.showDirectoryPicker();
  fileMap = {};
  modelFileList.value = [];
  await getFileList(rootDirHandle, "");
}

function loadModel(key: string) {
  let fileParam = fileMap[key];
  if (fileParam.extension === "glb") {
    emit("onSelected", fileParam.url);
    return;
  }

  let fr = new FileReader();
  fr.readAsText(fileParam.file);
  fr.addEventListener("progress", (e) => {
    console.log(e.loaded + "/" + e.total);
  });
  fr.addEventListener(
    "load",
    function () {
      let json = fr.result as string;
      let gltfObj = JSON.parse(json);
      gltfObj.buffers?.forEach((item: { uri: string }) => {
        changeUri(item, fileParam.baseUrl);
      });
      gltfObj.images?.forEach((item: { uri: string }) => {
        changeUri(item, fileParam.baseUrl);
      });

      let blob = new Blob([JSON.stringify(gltfObj)], {
        type: "application/json",
      });
      emit("onSelected", URL.createObjectURL(blob));
    },
    false
  );
}
</script>
<template>
  <div class="SelectFolder">
    <div @click="pickDirectory" class="btn">选择模型根目录</div>
    <div>
      <div
        v-for="item in modelFileList"
        :key="item"
        @click="loadModel(item)"
        class="file-item"
      >
        {{ item }}
      </div>
    </div>
  </div>
</template>
<style>
.SelectFolder {
  position: absolute;
  top: 10px;
  left: 10px;
}
.btn {
  cursor: pointer;
  background-color: white;
  line-height: 30px;
  padding: 0 10px;
}
.file-item:hover {
  cursor: pointer;
  background-color: aqua;
}
</style>
